package com.glq1218.springsecuritydemo.config;

import com.glq1218.springsecuritydemo.domain.entity.User;
import com.glq1218.springsecuritydemo.domain.model.LoginUser;
import com.glq1218.springsecuritydemo.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

/**
 * @author glq1218
 */
@Configuration
@RequiredArgsConstructor
public class SecurityConfig {
    private final UserService userService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // public static void main(String[] args) {
    //     System.out.println(new SecurityConfig(null).passwordEncoder().encode("user"));
    // }

    @Bean
    public UserDetailsService userDetailsService() {
        return username -> {
            User user = userService.findByUsername(username);
            if (user == null) {
                throw new UsernameNotFoundException("用户不存在");
            }
            return new LoginUser(user);
        };
    }

    @Bean
    public AuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsService());
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        authenticationProvider.setHideUserNotFoundExceptions(false);
        return authenticationProvider;
    }

    @Bean
    public AuthenticationManager authenticationManager() {
        return new ProviderManager(authenticationProvider());
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                // 允许跨域
                .cors().and()
                // 关闭默认登出
                .logout().disable()
                // 关闭csrf
                .csrf().disable()
                // 不通过Session获取SecurityContext
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeHttpRequests()
                // 允许匿名访问
                .requestMatchers(requestMatchersAnonymous()).anonymous()
                // 静态资源不需要任何限制
                .requestMatchers(HttpMethod.GET, requestMatchersPermitAll()).permitAll()
                // 除上面外的所有请求全部需要认证
                .anyRequest().authenticated();
        return http.build();
    }

    /**
     * 不需要任何限制url（静态资源）
     *
     * @return 字符串数组
     */
    private String[] requestMatchersPermitAll() {
        return new String[]{"/*.html"};
    }

    /**
     * 允许匿名访问url
     *
     * @return 字符串数组
     */
    private String[] requestMatchersAnonymous() {
        return new String[]{
                "/auth/**"
        };
    }
}
